//
//  NSString+ZLCategory.m
//  ZLCategory
//
//  Created by zhaozl on 2022/3/7.
//

#import "NSString+ZLCategory.h"
#import <CommonCrypto/CommonDigest.h>
#import "CommonCrypto/CommonHMAC.h"
#import <CommonCrypto/CommonCryptor.h>

@implementation NSString (ZLCategory)

- (BOOL)zl_isPureInt {
    NSScanner* scan = [NSScanner scannerWithString:self];
    int val;
    return [scan scanInt:&val] && [scan isAtEnd];
}

/// 是否是float型
- (BOOL)zl_isPureFloat {
    NSScanner* scan = [NSScanner scannerWithString:self];
    float val;
    return [scan scanFloat:&val] && [scan isAtEnd];
}

/// 是否是中文
- (BOOL)zl_isChinese {
    for (int i = 0; i < self.length; i++) {
        unichar ch = [self characterAtIndex:i];
        if (0x4E00 <= ch  && ch <= 0x9FA5) {
            return YES;
        }
    }
    return NO;
}

/// 判断是否含有文字
- (BOOL)zl_hasChinese {
    for (int i = 0; i < self.length; i ++) {
        int estimatePrice = [self characterAtIndex:i];
        if(estimatePrice > 0x4e00 && estimatePrice < 0x9fff) {
            return YES;
        }
    }
    return NO;
}

/// 字符串替换为星号
- (NSString *)zl_stars {
    NSString *stars = @"***************************************************";
    NSString *ori = [self stringByReplacingOccurrencesOfString:@" " withString:@""];
    return [stars substringWithRange:NSMakeRange(0, ori.length)];
}

/// 字符串显示最大3位小数
- (NSString *)zl_max3f {
    if (self) {
        if ([self zl_isPureFloat]) {
            NSRange range = [self rangeOfString:@"."];
            NSInteger decimalNum = self.length - range.location - 1;
            if (decimalNum >= 3) {
                return [NSString stringWithFormat:@"%.3f",self.floatValue];
            }
            return self;
        }
        return self;
    }
    return @"";
}

/// 判断字符串是否合法
- (BOOL)zl_isValidString {
    if (self) {
        if ([self isKindOfClass:[NSString class]]) {
            return [(NSString *)self length]>0;
        } else {
            return NO;
        }
    } else {
        return NO;
    }
}

/// 判断字符串是否为手机号
- (BOOL)zl_isValidPhoneNo {
    //    NSString *Regex =@"(13[0-9]|14[57]|15[012356789]|18[02356789])\\d{8}";
    NSString *Regex =@"1\\d{10}";
    NSPredicate *mobileTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", Regex];
    return [mobileTest evaluateWithObject:self];
}

/// 判断字符串是否包含另一字符串
/// @param aString 被包含字符串
- (BOOL)zl_hasString:(NSString *)aString {
    if ([NSString instancesRespondToSelector:@selector(containsString:)]) {
        return [self containsString:aString];
    } else {
        NSRange range = [self rangeOfString:aString];
        return range.location != NSNotFound;
    }
}

/// 版本比较
/// @param localVer 本地版本
- (NSComparisonResult)zl_versionCompare:(NSString *)localVer {
    NSArray *leftArr = [self componentsSeparatedByString:@"."];
    NSArray *rightArr = [localVer componentsSeparatedByString:@"."];
    if(leftArr.count != rightArr.count) {
        return NSOrderedSame;
    }
    NSInteger bitNum = leftArr.count;
    for (int i = 0; i < bitNum; i++) {
        NSInteger lv = [[leftArr objectAtIndex:i] integerValue];
        NSInteger rv = [[rightArr objectAtIndex:i] integerValue];
        if(lv > rv) {
            return NSOrderedDescending;
        } else if (lv < rv) {
            return NSOrderedAscending;
        }
    }
    return NSOrderedSame;
}

/// 判断字符串是否是当天(如果dateStr为2012-02-23，则格式应为yyyy-MM-dd 如果dateStr为20120223，则格式应为yyyyMMdd)
/// @param formatStr yyyy-MM-dd
- (BOOL)zl_isTodayWithFormatStr:(NSString *)formatStr {
    if (self == nil) {
        return NO;
    }
    
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat = formatStr;
    NSString *todayStr = [dateFormatter stringFromDate:[NSDate date]];
    if (todayStr == nil) {
        return NO;
    }
    
    return [self compare:todayStr] == NSOrderedSame;
}

/// 当天日期字符串
/// @param formatStr yyyy-MM-dd
+ (NSString *)zl_getTodayStr:(NSString *)formatStr {
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat = formatStr;
    NSString *todayStr = [dateFormatter stringFromDate:[NSDate date]];
    return todayStr;
}

/// 日期字符串
/// @param date 指定日期
+ (NSString *)zl_stringFromDate:(NSDate *)date {
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    //zzz表示时区，zzz可以删除，这样返回的日期字符将不包含时区信息。
    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSString *destDateString = [dateFormatter stringFromDate:date];
    return destDateString;
}

/// 解决英文显示不全的问题
/// @param font 字体
/// @param rect rect
- (NSString *)zl_getDspStringWithFont:(UIFont *)font dspRect:(CGRect)rect {
    NSString *strVal = self;
    NSInteger n1 = [strVal length];
    NSInteger n2 = [strVal lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
    
    if (n1 == n2) {
        CGSize constraintSize = CGSizeMake(300.0f, MAXFLOAT);
        
        NSDictionary* attributes = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
        CGRect recttmp = [strVal boundingRectWithSize:constraintSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil];
        CGSize labelSize = recttmp.size;
        
        if (labelSize.width > rect.size.width) {
            for (int i = 1; i< n1; i++) {
                strVal      = [strVal substringWithRange:NSMakeRange(0, n1-i)];
                
                NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
                CGRect recttmp = [strVal boundingRectWithSize:constraintSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil];
                labelSize = recttmp.size;
                
                if (labelSize.width <= rect.size.width) break;
            }
        }
    }
    
    return strVal;
}

/// 校验str 返回非nil 字符串
/// @param str 校验后结果
+ (NSString *)zl_getSafeString:(NSString *)str {
    return zl_getSafeString(str);
}

/// 校验str 返回非nil 字符串
/// @param str 校验后结果
NSString *zl_getSafeString(NSString *str) {
    if ([str isKindOfClass:[NSString class]]) {
        if ([str isEqualToString:@"<null>"]||[str isEqualToString:@"<NULL>"]) {
            return @"";
        } else if ([str isEqualToString:@"(null)"]||[str isEqualToString:@"(NULL)"]){
            return @"";
        } else if ([str isEqualToString:@"null"]||[str isEqualToString:@"NULL"]){
            return @"";
        }
        return (NSString *)str;
    } else if ([str isKindOfClass:[NSNumber class]]) {
        return [(NSNumber *)str stringValue];
    } else if ([str isKindOfClass:[NSNull class]]) {
        return @"";
    } else if (str == nil) {
        return @"";
    } else {
        return @"";
    }
}

/// 格式化json字段的值
/// @param value value
+ (NSString *)zl_formatJsonValue:(id)value {
    if (value == [NSNull null])
        return @"";
    else if ([value isKindOfClass:[NSString class]])
        return value;
    else if ([value isKindOfClass:[NSNumber class]])
        return [(NSNumber *)value stringValue];
    else if ([value isKindOfClass:[NSArray class]])
        return [(NSArray *)value componentsJoinedByString:@","];
    
    return @"";
}

/// 格式化json字段的值strValue
/// @param key key
/// @param dict 字典
+ (NSString *)zl_strValueForKey:(id)key ofDict:(NSDictionary *)dict {
    return [self zl_formatJsonValue:[dict objectForKey:key]];
}

/// 格式化json字段的值numberValue
/// @param key key
/// @param dict 字典
+ (NSNumber *)zl_numberValueForKey:(id)key ofDict:(NSDictionary *)dict {
    NSNumber *val   = nil;
    id objVal       = [dict objectForKey:key];
    
    if (objVal && objVal != [NSNull null])
    {
        if ([objVal isKindOfClass:[NSNumber class]])
            val = objVal;
        else if ([objVal isKindOfClass:[NSString class]])
        {
            NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
            val = [f numberFromString:objVal];
        }
    }
    
    return val;
}

/// 格式化json字段的值arrayValue
/// @param key key
/// @param dict 字典
+ (NSArray *)zl_arrayValueForKey:(id)key ofDict:(NSDictionary *)dict {
    id obj = [dict objectForKey:key];
    
    if ([obj isKindOfClass:[NSArray class]])
        return [NSArray arrayWithArray:obj];
    else
        return nil;
}

/// 格式化json字段的值dictionaryValue
/// @param key key
/// @param dict 字典
+ (NSDictionary *)zl_dictionaryValueForKey:(id)key ofDict:(NSDictionary *)dict {
    id obj = [dict objectForKey:key];
    
    if ([obj isKindOfClass:[NSDictionary class]])
        return obj;
    else
        return nil;
}

/// 校验数字、中文、字母
/// @param text text
+ (BOOL)zl_validateDigitOrLetterOrChinese:(NSString *)text {
    NSString *regex = @"^[a-z0-9A-Z\u4e00-\u9fa5]+$";
    NSPredicate *regexTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    return [regexTest evaluateWithObject:text];
}

/// json字符串转成字典或者数组
- (id)zl_transformFromJsonString {
    if (self == nil) {
        return nil;
    }
    
    NSData *jsonData = [self dataUsingEncoding:NSUTF8StringEncoding];
    NSError *error;
    id result = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
    if (error) {
        NSLog(@"json 解析失败 %@",error);
        return nil;
    }
    
    return result;
}

/// zl_document地址
+ (NSString *)zl_documentPath {
    static NSString * path = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)
                 objectAtIndex:0] copy];
    });
    return path;

}

/// cachePath
+ (NSString *)zl_cachePath {
    static NSString * path = nil;
    if (!path) {
        path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)
                 objectAtIndex:0] copy];
    }
    return path;
}

/// CurDate格式转换
+ (NSString *)zl_formatCurDate {
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSString *result = [dateFormatter stringFromDate:[NSDate date]];
    
    return result;
}

/// CurDay格式转换
+ (NSString *)zl_formatCurDay {
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy-MM-dd"];
    NSString *result = [dateFormatter stringFromDate:[NSDate date]];
    
    return result;
}

/// 获取appVersion
+ (NSString *)zl_getAppVer {
    return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
}

/// 去除所有空格
- (NSString*)zl_removeAllSpace {
    NSString* result = [self stringByReplacingOccurrencesOfString:@" " withString:@""];
    result = [result stringByReplacingOccurrencesOfString:@"    " withString:@""];
    return result;
}

/// 转换成URL
- (NSURL *)zl_toURL {
    NSCharacterSet *allowedCharacters = [NSCharacterSet URLQueryAllowedCharacterSet];;
    return [NSURL URLWithString:[self stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters]];
}

/// 是否是Email格式
- (BOOL)zl_isEmail {
    NSString *emailRegEx =
    @"(?:[a-z0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[a-z0-9!#$%\\&'*+/=?\\^_`{|}"
    @"~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\"
    @"x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-"
    @"z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5"
    @"]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-"
    @"9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21"
    @"-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])";
    
    NSPredicate *regExPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegEx];
    return [regExPredicate evaluateWithObject:[self lowercaseString]];
}

/// 是否为空
- (BOOL)zl_isEmpty {
    return nil == self
    || 0 == [[self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length];
}

/// 是否是身份证
- (BOOL)zl_isIdCard {
    NSString *regxRule = @"^[1-9]\\d{5}[1-2]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9]|X)$";//18位身份证号码验证
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regxRule];
    return [predicate evaluateWithObject:self];
}

/// HTML特殊字符转换
- (NSString *)zl_escapeHTML {
    NSMutableString *s = [NSMutableString string];
    
    int start = 0;
    int len = (int)[self length];
    NSCharacterSet *chs = [NSCharacterSet characterSetWithCharactersInString:@"<>&\""];
    
    while (start < len) {
        NSRange r = [self rangeOfCharacterFromSet:chs options:0 range:NSMakeRange(start, len-start)];
        if (r.location == NSNotFound) {
            [s appendString:[self substringFromIndex:start]];
            break;
        }
        
        if (start < r.location) {
            [s appendString:[self substringWithRange:NSMakeRange(start, r.location-start)]];
        }
        
        switch ([self characterAtIndex:r.location]) {
            case '<':
                [s appendString:@"&lt;"];
                break;
            case '>':
                [s appendString:@"&gt;"];
                break;
            case '"':
                [s appendString:@"&quot;"];
                break;
            case '&':
                [s appendString:@"&amp;"];
                break;
        }
        
        start =(int) r.location + 1;
    }
    
    return s;
}

/// HTML特殊字符转换
- (NSString *)zl_unescapeHTML {
    NSMutableString *s = [[NSMutableString alloc] init];
    NSMutableString *target = [self mutableCopy];
    NSCharacterSet *chs = [NSCharacterSet characterSetWithCharactersInString:@"&"];
    
    while ([target length] > 0) {
        NSRange r = [target rangeOfCharacterFromSet:chs];
        if (r.location == NSNotFound) {
            [s appendString:target];
            break;
        }
        
        if (r.location > 0) {
            [s appendString:[target substringToIndex:r.location]];
            [target deleteCharactersInRange:NSMakeRange(0, r.location)];
        }
        
        if ([target hasPrefix:@"&lt;"]) {
            [s appendString:@"<"];
            [target deleteCharactersInRange:NSMakeRange(0, 4)];
        } else if ([target hasPrefix:@"&gt;"]) {
            [s appendString:@">"];
            [target deleteCharactersInRange:NSMakeRange(0, 4)];
        } else if ([target hasPrefix:@"&quot;"]) {
            [s appendString:@"\""];
            [target deleteCharactersInRange:NSMakeRange(0, 6)];
        } else if ([target hasPrefix:@"&#39;"]) {
            [s appendString:@"'"];
            [target deleteCharactersInRange:NSMakeRange(0, 5)];
        }else if ([target hasPrefix:@"&#039;"]) {
            [s appendString:@"'"];
            [target deleteCharactersInRange:NSMakeRange(0, 6)];
        } else if ([target hasPrefix:@"&amp;"]) {
            [s appendString:@"&"];
            [target deleteCharactersInRange:NSMakeRange(0, 5)];
        } else if ([target hasPrefix:@"&hellip;"]) {
            [s appendString:@"…"];
            [target deleteCharactersInRange:NSMakeRange(0, 8)];
        } else {
            [s appendString:@"&"];
            [target deleteCharactersInRange:NSMakeRange(0, 1)];
        }
    }
    
    return s;
}

/// 字符串移除HTML
- (NSString *)zl_stringByRemovingHTML {
    NSString *html = self;
    NSScanner *thescanner = [NSScanner scannerWithString:html];
    NSString *text = nil;
    
    while ([thescanner isAtEnd] == NO) {
        [thescanner scanUpToString:@"<" intoString:NULL];
        [thescanner scanUpToString:@">" intoString:&text];
        html = [html stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%@>",text] withString:@" "];
    }
    return html;
}

/// MD5加密
- (NSString *)zl_MD5 {
    if(self == nil || [self length] == 0) {
        return nil;
    }
    // Create pointer to the string as UTF8
    const char* ptr = [self UTF8String];
    unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
    
    // Create 16 byte MD5 hash value, store in buffer
    CC_MD5(ptr, (CC_LONG)strlen(ptr), md5Buffer);
    
    // Convert MD5 value in the buffer to NSString of hex values
    NSMutableString* output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
    for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
        [output appendFormat:@"%02x",md5Buffer[i]];
    }
    
    return output;
}

/// URL编码
- (NSString * )zl_URLEncode {
    NSString *result =
    CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                              (CFStringRef)self,
                                                              NULL,
                                                              CFSTR("!*'();:@&;=+$,/?%#[] "),
                                                              kCFStringEncodingUTF8));
    return [result zl_trim];
}

/// 去除空格
-(NSString *)zl_trim {
    return  [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}

/// 主要功能：通过文字内容，确定其显示宽度
/// @param font 字体
/// @param size 大小
- (CGSize)zl_sizeWithFont:(UIFont *)font maxSize:(CGSize)size {
    NSDictionary *dict = @{NSFontAttributeName:font};
    CGSize resultSize = [self boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size;
    return resultSize;
}


/// 主要功能：通过文字内容，字体，富文本字典，确定其宽高
/// @param font 字体
/// @param attributes 富文本字典
/// @param size 大小
- (CGSize)zl_sizeWithFont:(UIFont *)font attributes:(NSDictionary *)attributes maxSize:(CGSize)size {
    NSMutableDictionary *dict = [attributes mutableCopy];
    dict[NSFontAttributeName] = font;
    CGSize resultSize = [self boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size;
    return resultSize;
}

@end
